06. Reading in Text Files

Reading in Text Files

The Standard Library includes functionality for reading text files line by line. You can then parse each line of the text file one line at a time.

Say, for example, you have a text file with numbers and commas representing a 3 by 4 matrix:

1, 6, 2, 10.5
11, 15.2, 2, 21
3, 9, 1, 7.5

You want to read in this file and create a 2D vector to represent the matrix. Here is code to do this, and then below you can run the code to see that it works.

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

int main() {

    // initialize string variables for reading in text file lines 
    string line;
    stringstream ss;

    // initialize variables to hold the matrix
    vector < vector <float> > matrix;
    vector<float> row;

    // counter for characters in a text file line
    float i;

    // read in the file
    ifstream matrixfile ("matrix.txt");

    // read in the matrix file line by line
    // parse the file

    if (matrixfile.is_open()) {
        while (getline (matrixfile, line)) {

            // parse the text line with a stringstream
            // clear the string stream to hold the next line
            ss.clear();
            ss.str("");
            ss.str(line);
            row.clear();

            // parse each line and push to the end of the row vector
            // the ss variable holds a line of text
            // ss >> i puts the next character into the i variable. 
            // the >> syntax is like cin >> some_value or cout << some_value
            // ss >> i is false when the end of the line is reached

            while(ss >> i) {
                row.push_back(i);

                if (ss.peek() == ',' || ss.peek() == ' ') {
                    ss.ignore();
                }
            }

            // push the row to the end of the matrix
            matrix.push_back(row);
        }

        matrixfile.close();

        // print out the matrix
        for (int row = 0; row < matrix.size(); row++) {
            for (int column = 0; column < matrix[row].size(); column++) {
                cout << matrix[row][column] << " " ;
            }
            cout << endl; 
        }
    }

    else cout << "Unable to open file";

    return 0;
}

Here is a demonstration of how to read in data from a text file. The code reads in a tile file that contains data for a matrix. Then the code outputs the matrix to the terminal display. Read through the code to try to figure out what it does. Then run the code by pressing the "Test Run" button.

Below the demo, there is an explanation of what the code is doing.

Start Quiz:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

int main() {

    // initialize string variables for reading in text file lines 
    string line;
    stringstream ss;

    // initialize variables to hold the matrix
    vector < vector <float> > matrix;
    vector<float> row;

    // counter for characters in a text file line
    float i;

    // read in the file
    ifstream matrixfile ("matrix.txt");

    // read in the matrix file line by line
    // parse the file

    if (matrixfile.is_open()) {
        while (getline (matrixfile, line)) {

            // parse the text line with a stringstream
            // clear the string stream to hold the next line
            ss.clear();
            ss.str("");
            ss.str(line);
            row.clear();

            // parse each line and push to the end of the row vector
            while(ss >> i) {
                row.push_back(i);

                if (ss.peek() == ',' || ss.peek() == ' ') {
                    ss.ignore();
                }
            }

            // push the row to the end of the matrix
            matrix.push_back(row);
        }

        matrixfile.close();

        // print out the matrix
        for (int row = 0; row < matrix.size(); row++) {
            for (int column = 0; column < matrix[row].size(); column++) {
                cout << matrix[row][column] << " " ;
            }
            cout << endl; 
        }
    }

    else cout << "Unable to open file";

    return 0;
}
1, 6, 2, 10.5
11, 15.2, 2, 21
3, 9, 1, 7.5

There are two parts of the code that you haven't seen yet: fstream and sstream. Both of these files are part of the C++ Standard Library.

fstream provides functions and classes for reading in and outputting files.

This line of code reads in the file "matrix.txt" and then creates an object called "matrixfile" that you can use for reading in the text file:

    ifstream matrixfile ("matrix.txt");

The if statement that follows checks that the file opened correctly:

    if (matrixfile.is_open()) {

and then a while loop reads the file one line at a time. Each line is placed into a variable called "line":

    if (matrixfile.is_open()) {
        while (getline (matrixfile, line)) {

If you look at the text file, each line in this case is a string consisting of floats, commas and spaces. For example, "1, 6, 2, 10.5".

The sstream file in the Standard Library provides functionality for manipulating and parsing the string. In the code, you'll see that first a sstream object was declared and then later the ss object was used to cycle through and parse each line of the text file:

stringstream ss;

....

ss.clear();
ss.str("");
ss.str(line);

while(ss >> i) {
    row.push_back(i);

    if (ss.peek() == ',' || ss.peek() == ' ') {
        ss.ignore();
    }
}```

In other words, the code finds a float number and appends the number to the vector called row. The line `ss.peek()` looks at the next character to see if it is a comma or a space and ignores commas or spaces.

Note as well that when you are done with reading in the file, it's a good habit to close the file.

matrixfile.close();
```

If you ever write a programming that opens many files simultaneously and never closes them, your program could crash.